﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Physis.Core.Sponsor {

    public class SponsorType : CoreConfigurationObject {
        
        #region Private Properties

        private List<SponsorTypeAllowedParent> allowedParents = new List<SponsorTypeAllowedParent> ();

        #endregion 


        #region Public Properties

        public List<SponsorTypeAllowedParent> AllowedParents { get { return allowedParents; } set { allowedParents = value; } }

        #endregion 

        
        #region Constructors

        public SponsorType (Application forApplication) : base (forApplication) {

            return;

        }

        public SponsorType (Application forApplication, Int64 forId) : base (forApplication, forId) {

            return;

        }

        public SponsorType (Application forApplication, String forName) : base (forApplication, forName) {

            return;

        }

        #endregion


        #region Database Functions

        protected override Dictionary<String, String> Validate () {

            Dictionary<String, String> validationErrors = base.Validate ();


            // CHECK TO SEE THAT THERE IS AT LEAST ONE ALLOWED PARENT THAT IS ENABLED

            // DEFAULT CAN NEVER BE DISABLED, WE HAVE TO CHECK IT INDEPENDENTLY SO IT 
            
            // DOESN'T IMPLODE THE LINQ QUERY WITH A NULL VALUE (NULL PARENT SPONSOR TYPE OBJECT) 

            // WE DON'T NEED TO MAKE SURE THAT THEY ARE ENABLED IF THIS SPONSOR TYPE IS EXPLICITLY DISABLED.

            if ((!AllowedParent (0)) && (Enabled)) { 

                // DEFAULT IS NOT IN ALLOWED PARENTS, WE NEED TO MAKE SURE THAT THERE IS AT 

                // LEAST ONE ALLOWED PARENT THAT IS ENABLED AND AVAILABLE FOR USE

                // IF THE DEFAULT IS ALLOWED, THEN WE KNOW THAT IT CANNOT BE SET TO DISABLED

                if ((from currentAllowedParent in allowedParents where currentAllowedParent.ParentSponsorType.Enabled select currentAllowedParent).Count () == 0) {

                    // NO ALLOWED PARENTS THAT ARE ENABLED 

                    validationErrors.Add ("Allowed Parents", "No defined allowed parents that are enabled available.");

                }

            }
            

            return validationErrors;

        }

        public override void MapDataFields (System.Data.DataRow currentRow) {
            
            base.MapDataFields (currentRow);



            return;

        }

        protected override Boolean LoadChildObjects () {

            String selectStatement = "SELECT SponsorTypeAllowedParent.* ";

            selectStatement += "  FROM SponsorTypeAllowedParent";

            selectStatement += "  WHERE SponsorTypeId = " + Id;


            System.Data.DataTable dataTable = Application.EnvironmentDatabase.SelectDataTable (selectStatement);

            foreach (System.Data.DataRow currentDataRow in dataTable.Rows) {

                SponsorTypeAllowedParent sponsorTypeAllowedParent = new SponsorTypeAllowedParent (Application);

                sponsorTypeAllowedParent.MapDataFields (currentDataRow);

                allowedParents.Add (sponsorTypeAllowedParent);

            }
            
            return true;

        }

        public override Boolean Save () {

            Boolean success = false;

            try {

                Dictionary<String, String> validationErrors = Validate ();

                if (validationErrors.Count > 0) {

                    Application.SetLastException (new Exception ("Invalid [" + validationErrors.Keys.First () + "]: " + validationErrors.Values.First ()));

                    return false;

                }

                UpdateModifiedToSessionUser ();


                Application.EnvironmentDatabase.BeginTransaction ();

                System.Data.IDbCommand command = Application.EnvironmentDatabase.CreateCommand (ObjectType + "_InsertUpdate");

                command.CommandType = System.Data.CommandType.StoredProcedure;


                Application.EnvironmentDatabase.AppendCommandParameter (command, "Id", Id);

                Application.EnvironmentDatabase.AppendCommandParameter (command, "Name", Name, 60);

                Application.EnvironmentDatabase.AppendCommandParameter (command, "Description", Description, 999);


                Application.EnvironmentDatabase.AppendCommandParameter (command, "Enabled", Enabled);

                Application.EnvironmentDatabase.AppendCommandParameter (command, "ModifiedId", Application.Session.UserAccountName, 60);

                success = (command.ExecuteNonQuery () > 0);

                if (success) { SetIdentity (); }

                else { throw Application.EnvironmentDatabase.LastException; }


                // DELETE ALL ALLOW PARENT RECORDS TO RE-INSERT THEM 

                String deleteStatement = "DELETE FROM SponsorTypeAllowedParent WHERE SponsorTypeId = " + Id;

                success = Application.EnvironmentDatabase.ExecuteSqlStatement (deleteStatement);

                if (!success) { throw Application.EnvironmentDatabase.LastException; }


                foreach (SponsorTypeAllowedParent currentSponsorTypeAllowedParent in allowedParents) {

                    currentSponsorTypeAllowedParent.Application = Application; // RESET APPLICATION REFERENCE 

                    currentSponsorTypeAllowedParent.SponsorTypeId = Id; // RESET OWNING OBJECT ID

                    success = success && (currentSponsorTypeAllowedParent.Save ());

                    if (!success) { throw Application.LastException; }

                }

                Application.EnvironmentDatabase.CommitTransaction ();

            }

            catch (Exception exception) {

                success = false;

                Application.SetLastException (exception);

                Application.EnvironmentDatabase.RollbackTransaction ();

            }

            return success;

        }

        public override Boolean Delete () {

            return base.DeleteFromDatabase (DeleteStatementById (), Application.EnvironmentDatabase);

        }

        #endregion 


        #region Public Methods

        public Boolean AllowedParent (Int64 parentSponsorTypeId) {

            Boolean allowed = false;

            allowed = ((from currentParentSponsorTypeAllowedParent in AllowedParents

                       where (currentParentSponsorTypeAllowedParent.ParentSponsorTypeId == parentSponsorTypeId)

                       select currentParentSponsorTypeAllowedParent).Count () > 0);

            return allowed;

        }

        public Boolean AllowedChild (Int64 childSponsorTypeId) {

            if (childSponsorTypeId == Id) { return false; } // CANNOT BE CHILD OF ONE SELF

            return (Application.Core.Sponsor.SponsorType (childSponsorTypeId, true).AllowedParent (Id));

        }

        #endregion 

    }

}
